package com.liming.common.util;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @author liming
 * @date 2025/6/19
 */
@Slf4j
public class ThreadPoolExecutorUtils {

    private static final String THREAD_NAME_PREFIX = "ming-pool-thread";

    /**
     * @param corePoolSize    线程池的核心线程数量
     * @param maximumPoolSize 线程池的最大线程数
     * @param keepAliveTime   当线程数大于核心线程数时，多余的空闲线程存活的最长时间
     * @param unit            时间单位
     * @param workQueue       任务队列，用来储存等待执行任务的队列
     * @param threadFactory   线程工厂，用来创建线程，一般默认即可
     * @param handler         拒绝策略，当提交的任务过多而不能及时处理时，我们可以定制策略来处理任务
     * @return ExecutorService
     */
    public static ThreadPoolExecutor create(int corePoolSize,
                                            int maximumPoolSize,
                                            long keepAliveTime,
                                            TimeUnit unit,
                                            BlockingQueue<Runnable> workQueue,
                                            ThreadFactory threadFactory,
                                            RejectedExecutionHandler handler) {
        log.info("创建线程池，核心线程数：{}，最大线程数：{}，空闲线程存活时间：{}，时间单位：{}，任务队列：{}，线程工厂：{}，拒绝策略：{}",
                corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        if (threadFactory == null) {
            threadFactory = Executors.defaultThreadFactory();
        }
        if (handler == null) {
            handler = new ThreadPoolExecutor.AbortPolicy();
        }
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    /**
     * 创建线程工厂
     *
     * @return ThreadFactory
     */
    public static ThreadFactory createThreadFactory() {
        return new ThreadFactoryBuilder()
                .setNameFormat(THREAD_NAME_PREFIX + "-%d")
                .setDaemon(true)
                .build();
    }

    /**
     * 获取CPU核数
     * 为了计算线程池的线程数量，我们需要获取CPU核数
     * CPU密集型任务 N + 1
     * IO密集型任务 2N
     *
     * @return CPU核数
     */
    public static int getCorePoolSize(String taskType) {
        int n = Runtime.getRuntime().availableProcessors();
        return "CPU".equals(taskType) ? n + 1 : 2 * n;
    }

    /**
     * 预热线程池中的一个
     *
     * @param threadPoolExecutor 线程池
     * @return 是否预热成功 （预热失败说明线程池中核心线程已经全部启动）
     */
    public static boolean preheatOneCoreThreadOfPool(ThreadPoolExecutor threadPoolExecutor) {
        return threadPoolExecutor.prestartCoreThread();
    }

    /**
     * 预热线程池中的所有核心线程
     *
     * @param threadPoolExecutor 线程池
     * @return 预热成功的核心线程数量
     */
    public static int preheatAllCoreThreadOfPool(ThreadPoolExecutor threadPoolExecutor) {
        return threadPoolExecutor.prestartAllCoreThreads();
    }
}
